/* \image html zapisOpcji.png "zapis opcji QSettings" */
/**
    \page stronaZapisOpcji O zapisie opcji słów kilka

    QSettings jest wbudowaną klasą Qt'a dziedziczącą po QObject. Jej zadaniem jest zapisywanie opcji do rejestrów tak, aby program zapamiętywał ustawienia zapisane w programie.
    Wartości przechowywane za pomocą QSettings są typu QVariant. Przy zapisywaniu następuje automatyczna konwersja do typu QVariant. Natomiast przy odczytywaniu z QSettings należy posłużyć się odpowiednimi funkcjami dostarczanymi przez klasę QVariant konwertującymi typ QVariant do pierwotnego typu.

    W przypadku naszego programu klasa QSettings jest wykorzystywana do:
    <ul>
    <li> komunikacji między oknem opcji a odpowiadającymi im klasami wykonawczymi.
    Uogólniając komunikacja ta polega na zapisaniu opcji na dysku i wysłanie sygnału (o dokonanym zapisie) przez klasę opcji (np. klasa mainOption, intensityTraffic), a następnie odczytaniu opcji (po odebraniu sygnału) i dokonanie odpowiednich zmian przez klasę wykonawczą (klasa rsim).
    Więcej na temat sygnałów można przeczytać na stronach dokumentacji Qt.
    <li> zapis wartości wpisanych przez użytkownika jako domyślne przy kolejnym uruchomieniu programu
    Klasa opcji dba o to, aby zapisać wartości opcji, a następnie wczytać je przy ponownym uruchomieniu programu.
    <li> tymczasowy zapis wartości na potrzeby programu
    Do użytku wewnętrznego przy dynamicznym tworzeniu widgetów.
    </ul>

    Zapisywane zmienne są w postaci pary: klucz(nazwa zmiennej) i wartość. Mogą być hierarchizwane w grupach (zobacz \htmlonly <a href="http://doc.qt.nokia.com/4.7/qsettings.html">dokumentację Qt</a> \endhtmlonly) w sposób podobny do struktury katalogowej.
    W przypadku braku zapisanych opcji na dysku lokalnym w programie wczytywane są opcje domyślne.

    Dane są zapisywane na dysku lokalnym (więcej informacji w dokumentacji Qt)
    Dla Windows 7 ścieżka dostępu jest następująca: HKEY_CURRENT_USER/Software/TabMar/RoundaboutSimulator

    Struktura zapisanych opcji RoundaboutSimulator jest przedstawiona poniżej.
    Każda podgrupa oznaczona literą x może pojawić się wielokrotnie (x przyjmie wtedy wartości porządkowe). Zmienna size jest domyślna dla QSettings i jej wartość jest równa liczbie podgrup x w grupie.

RoundaboutSimulator:
<ol>
<li><b>"Branch"</b> - opisuje gałęzie na rondzie

<ul>
<li>size
<li>x - kolejne grupy x są tworzone dla każdej gałęzi na rondzie
<ul>
<li>\link types.h::Dependence dependences \endlink - zależność między tą a następną gałęzią. Zapisywana w postaci liczbowej enum.
<li>\link types.h::Direction direction \endlink - kierunek ulicy (wjazd/zjazd)
<li>\link Branch::_numLanes numLanes \endlink - liczba pasów na gałęzi jest zależna od liczby pasów na rondzie
<li>\link Branch::_hasZebra zebra \endlink   - zmienna informująca czy rysować pasy na danej gałęzi. Zapisana wartość jest równa 0 (jeżeli pasów na jezdni ma nie być) lub 2(w przeciwnym wypadku)
</ul>
</ul>

<li><b>"entryTraffic"</b> - opisuje natężenie samochodów na wjazdach

<ul>
<li>size
<li>x - kolejne grupy x są tworzone dla każdego wjazdu na rondzie
<ul>
<li>entryIntensity - natężenie samochodów wjeżdżających na rondo na gałęzi o numerze entryNumber. Podawane w postaci liczbowej z przedziału od 0-100%. Zobacz: \link Branch::_frequencySpan frequencySpan \endlink
<li>entryNumber - numer wjazdu do którego odnosi się entryIntensity. To _nie_ jest numer gałęzi!
</ul>
</ul>

<li><b>"IntensityPedestrian"</b> - opisuje natężenie pieszych na pasach

<ul>
<li>size
<li>x - kolejne grupy x są tworzone dla każdej gałęzi (na której są pasy) na rondzie
<ul>
<li>intensityPedestrian - wartość natężenia zapisywana w postaci indexów do QComboBoxów. Możliwe są następujące indexy (z odpowiadającymi im tekstami): 0 - wcale, 1 - rzadko, 2 - średnio, 3 - często, 4 - strajk
<li>numBranches - numer gałęzi na których są pasy
</ul>
</ul>

<li><b>"outletTraffic"</b> - opisuje natężenie samochodów na wyjazdach (dla kazdego wjazdu)

<ul>
<li>size
<li>entry y - oznacza numer wjazdu, dla którego są zapisywane wartości natężenia wyjazdów
<ul>
<li>size
<li>x - kolejne grupy x są tworzone dla każdego wyjazdu na rondzie
<ul>
<li>outletIntensity - natężenie samochodów zjeżdżających z ronda na gałąź o numerze outletNumber. Podawane w postaci liczbowej z przedziału od 0-100%. Zobacz: \link Branch::_trafficDistribution trafficDistribution \endlink
<li>outletNumber - numer gałęzi(!) do którego odnosi się outletIntensity.
</ul>
</ul>
</ul>

<li><b>"Rails"</b> - opisuje torowiska na rondzie
<ul>
<li>size
<li>x - kolejne grupy x są tworzone dla każdego torowiska na rondzie
<ul>
<li>\link Rails::_from from \endlink  - źródło torów. Zapisywane w postaci inta przedstawiającego rzeczywisty numer gałęzi
<li>\link Rails::_fromRailBed fromRailBed \endlink  - podłoże źródła torów. Zapisywane w postaci inta przedstawiającego rzeczywisty numer gałęzi
<li>\link Rails::_to to \endlink  - cel torów. Zapisywane w postaci indexów do _numerCeluComboBox
<li>\link Rails::_toRailBed toRailBed \endlink  - podłoże celu torów. Zapisywane w postaci indexów do _podlozeCeluComboBox
</ul>
</ul>

<li>\link QRoundabout::_barriersVisible drawBarriers \endlink  - zmienna przechowująca informacji o tym, czy rysować bariery na rondzie, czy nie. Zapisana wartość 0 oznacza, ze nie rysować, natomiast wartośc 2 - rysować (zobacz \htmlonly <a href="http://doc.qt.nokia.com/4.7/qcheckbox.html#checkState">CheckBox::checkState()</a> \endhtmlonly)
<li>\link QRoundabout::_laneWidth laneWidth \endlink  - szerokość pasa. Możliwy zakres: 10-100.
<li>\link QRoundabout::_numBranches numBranches \endlink - liczba gałęzi na rondzie. Wartość minimalna 2. Wartość maksymalna 10.
<li>numRails - liczba torowisk na rondzie. Wartośc minimalna: 0 (brak torowisk). Wartość maksymalna: 10
<li>\link QRoundabout::_radius radius \endlink  - promień ronda. Zakres: <50, 500>
<li>\link QRoundabout::_numLanes rimNumLanes \endlink  - liczba pasów na rondzie z zakresu <1,5>.
</ol>
*/

#include "mainOptions.h"
#include "roundaboutPages.h"
#include "roadsPage.h"
#include "tramsPage.h"
#include <QVBoxLayout>
#include <QTextCodec>
#include <QToolBox>
#include <QListWidget>
#include <QStackedWidget>
#include <QPushButton>
#include <QHBoxLayout>
#include <QSettings>
#include <QDebug>


/*!
  Jedyny konstruktor. Tworzy okienko opcji w skład których wchodzą trzy strony: rondoPage, ulicePage i tramwajePage
  oraz dwa przyciski: closeButton i anulujButton.
  Na końcu wywoływana jest funkcja Options::readSettings().
  */
Options::Options(QWidget *parent)
    : QDialog(parent)
{
    QTextCodec::setCodecForTr (QTextCodec::codecForName("UTF-8"));
    contentsWidget = new QListWidget;
    contentsWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::MinimumExpanding);
    contentsWidget->setViewMode(QListView::IconMode);
    contentsWidget->setIconSize(QSize(64, 56));
    contentsWidget->setMovement(QListView::Static);
    contentsWidget->setMaximumWidth(120);
    contentsWidget->setMinimumHeight(270);
    contentsWidget->setSpacing(12);

    pagesWidget = new QStackedWidget;
    pagesWidget->addWidget(rondoPage = new RoundaboutPage(this));
    pagesWidget->addWidget(ulicePage = new RoadsPage(this, rondoPage->getNumLanesOnBranch() ));
    pagesWidget->addWidget(tramwajePage = new TramsPage(this));// BRAK TRAMWAJÓW (zakomentować, jeśli nie chcemy tej zakładki)
    closeButton = new QPushButton(tr("OK"));
    anulujButton = new QPushButton(tr("Anuluj"));

    connect( rondoPage, SIGNAL( changeNumLane(int) ), ulicePage, SLOT( changeNumLanesFromRoadPages(int) ) );
    connect( ulicePage, SIGNAL( changeNumBranchesForTram(int) ), tramwajePage, SLOT( numBranchesChanged(int) ) ) ;
    connect( ulicePage, SIGNAL( directionChanged(int)), tramwajePage, SLOT(roadsDirectionChanged(int)));

    rondoPage->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);

    createIcons();
    contentsWidget->setCurrentRow(1);

    connect(anulujButton, SIGNAL(clicked()), this, SLOT(reject()));
    connect(closeButton, SIGNAL(clicked()), this, SLOT(saveSettings()));

    QHBoxLayout *horizontalLayout = new QHBoxLayout();
    horizontalLayout->addWidget(contentsWidget);
    horizontalLayout->addWidget(pagesWidget, 1);


    QHBoxLayout *buttonsLayout = new QHBoxLayout;
    buttonsLayout->addStretch(1);
    buttonsLayout->addWidget(closeButton);
    buttonsLayout->addWidget(anulujButton);

    QVBoxLayout *mainLayout = new QVBoxLayout;
    mainLayout->addLayout(horizontalLayout, 1);
    mainLayout->addSpacing(12);
    mainLayout->addLayout(buttonsLayout);
    setLayout(mainLayout);

    setWindowTitle(tr("Konfiguracja Ronda"));
    readSettings();
}

Options::~Options()
{

}

/*!
Tworzy ikonki z lewej strony do nawigacji między stronami
  */
void Options::createIcons()
{
    QListWidgetItem *rondoButton = new QListWidgetItem(contentsWidget);
    rondoButton->setIcon(QIcon(":/images/branches.png"));
    rondoButton->setText(tr("Opcje Ronda"));
    rondoButton->setTextAlignment(Qt::AlignHCenter);
    rondoButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);

    QListWidgetItem *uliceButton = new QListWidgetItem(contentsWidget);
    uliceButton->setIcon(QIcon(":/images/road.png"));
    uliceButton->setText(tr("Ulice"));
    uliceButton->setTextAlignment(Qt::AlignHCenter);
    uliceButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);

    QListWidgetItem *tramButton = new QListWidgetItem(contentsWidget);
    //tramButton->setIcon(QIcon(":/images/smurfette.png"));
    tramButton->setText(tr("Tramwaje"));
    tramButton->setTextAlignment(Qt::AlignHCenter);
    tramButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);

    connect(contentsWidget,
            SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)),
            this, SLOT(changePage(QListWidgetItem*,QListWidgetItem*)));
}

/*!
    Funkcja(slot) umożliwia zmianę strony (rondo, ulice, tramwaje) na podstawie zmiany itemu w contentsWidget.
*/
void Options::changePage(QListWidgetItem *current, QListWidgetItem *previous)
{
    if (!current)
        current = previous;

    pagesWidget->setCurrentIndex(contentsWidget->row(current));
}

/*!
Zapisuje konfiguracje zapisane na poszczególnych stronach. W przypadku klas RoadsPage oraz TramsPage zapisywanie odbywa się z
wykorzystaniem funkcji należących do tych klas.
Wartości są zapisywane na dysk przy pomocy QSettings. Więcej informacji można znaleźć na osobnej \link stronaZapisOpcji stronie \endlink.
  */
void Options::saveSettings()
{
    QSettings s("TabMar", "RoundaboutSimulator"); //C:\settings

    //zapis strony RONDO ok
    s.setValue("radius", rondoPage->getRadius());
    s.setValue("laneWidth", rondoPage->getWidthLane());
    s.setValue("rimNumLanes", rondoPage->getRimNumLanes());
    s.setValue("drawBarriers", rondoPage->drawBarriers());
    s.setValue("numRails", tramwajePage->getNumRails());
    //zapis strony ULICE
    ulicePage->saveRoadsSettings();
    //zapis strony TRAMWAJE
    tramwajePage->saveTramsSettings();

    //żeby Marek wiedział, że użytkownik kliknął OK :)
    QDialog::accept();
}

/*!
Funkcja odczytuje konfiguracje zapisane na poszczególnych stronach przy wykorzystaniu funkcji należących do klas tych stron.
*/
void Options::readSettings()
{
    //odczyt strony RONDO
    rondoPage->readRoundaboutSettings();
    //odczyt strony ULICE
    ulicePage->readRoadsSettings();
    //odczyt strony TRAMWAJE
    tramwajePage->readTramsSettings();
}

/*!
  \return zwraca liczbę gałęzi (na podstawie informacji z klasy RoadsPage)
  */
int Options::getNumBranches()
{
    return ulicePage->getNumBranches();
}

/*!
  \param i - numer gałęzi, dla której zwracany jest kierunek
  \return zwraca kierunek i-tej gałęzi (na podstawie informacji z klasy RoadsPage) w postaci wyliczeniowej Direction
  */
Direction Options::getBranchDirection(int i)
{
    return ulicePage->getBranchDirection(i);
}

/*!
  \param i - numer gałęzi, dla której zwracana jest zależność
  \return zwraca zależność i-tej gałęzi (na podstawie informacji z klasy RoadsPage) w postaci wyliczeniowej Dependence
  */
Dependence Options::getBranchDependence(int i)
{
    return ulicePage->getBranchDependence(i);
}
